package com.whfc.fse.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.BindFlag;
import com.whfc.common.enums.NetState;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ListData;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.PageUtil;
import com.whfc.fse.dao.FseLiftDataMapper;
import com.whfc.fse.dao.FseLiftMapper;
import com.whfc.fse.dto.*;
import com.whfc.fse.entity.FseLift;
import com.whfc.fse.entity.FseLiftData;
import com.whfc.fse.enums.FseLiftSide;
import com.whfc.fse.param.*;
import com.whfc.fse.service.FseLiftService;
import com.whfc.fuum.service.SysDeptService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 升降机 服务
 *
 * @author GuoDong_Sun
 * @date 2020/4/10
 */
@DubboService(interfaceClass = FseLiftService.class, version = "1.0.0", timeout = 5000)
public class FseLiftServiceImpl implements FseLiftService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private FseLiftMapper fseLiftMapper;

    @Autowired
    private FseLiftDataMapper fseLiftDataMapper;


    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Override
    public PageData<FseLiftDTO> list(Integer pageNum, Integer pageSize, Integer deptId, String keyword,
                                     Integer bindFlag, Integer netState) {
        logger.info("升降机列表服务,pageNum:{},pageSize:{},deptId:{},keyword:{}",
                pageNum, pageSize, deptId, keyword);
        PageHelper.startPage(pageNum, pageSize);
        List<FseLiftDTO> list = fseLiftMapper.selectFseLiftByDeptId(deptId, keyword, bindFlag, netState);
        PageHelper.clearPage();

        for (FseLiftDTO fseLiftDTO : list) {
            // 处理操作手
            fseLiftDTO.setOperatorList(parseOperators(fseLiftDTO.getOperators()));
            fseLiftDTO.setOperators(null);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public ListData<OpenApiFseLiftDTO> list(Integer deptId) throws BizException {
        logger.info("升降机列表服务,deptId:{}", deptId);
        List<OpenApiFseLiftDTO> list = fseLiftMapper.selectOpenApiFseLiftByDeptId(deptId);
        for (OpenApiFseLiftDTO fseLiftDTO : list) {

            // 处理操作手
            List<FseOperatorDTO> operatorList = parseOperators(fseLiftDTO.getOperators());
            fseLiftDTO.setOperatorList(operatorList);
            fseLiftDTO.setOperators(null);

            // 处理监控设备
            List<FseLiftFvsDeviceDTO> fvsDeviceList = parseFvsDevices(fseLiftDTO.getFvsDevices());
            List<OpenApiFseDeviceDTO> openApiFseDeviceList = new ArrayList<>();
            for (FseLiftFvsDeviceDTO fseLiftFvsDeviceDTO : fvsDeviceList) {
                OpenApiFseDeviceDTO fseDeviceDTO = new OpenApiFseDeviceDTO();
                fseDeviceDTO.setDeviceId(fseLiftFvsDeviceDTO.getFvsDeviceId());
                fseDeviceDTO.setName(fseLiftFvsDeviceDTO.getFvsDeviceName());
                openApiFseDeviceList.add(fseDeviceDTO);
            }
            fseLiftDTO.setVideoList(openApiFseDeviceList);
            fseLiftDTO.setFvsDevices(null);
        }
        return new ListData<>(list);
    }

    @Override
    public void add(FseLiftAddParam request) {
        logger.info("添加升降机服务,param:{}", request.toString());
        String code = request.getCode();
        Integer deptId = request.getDeptId();
        FseLift fseLift = fseLiftMapper.selectByDeptIdAndCode(deptId, code);
        if (fseLift != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }
        FseLift record = new FseLift();
        BeanUtils.copyProperties(request, record);
        //处理操作手
        List<FseOperatorDTO> operatorList = request.getOperatorList();
        if (operatorList != null) {
            String operators = JSON.toJSONString(operatorList);
            record.setOperators(operators);
        }
        fseLiftMapper.insertSelective(record);
        //初始化升降机信息
        initLiftData(record.getId());
    }

    @Override
    public void edit(FseLiftEditParam request) {
        logger.info("编辑升降机服务,param:{}", request.toString());
        Integer liftId = request.getLiftId();
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        if (fseLift == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该升降机不存在");
        }
        String code = request.getCode();
        Integer deptId = fseLift.getDeptId();
        FseLift fseLift1 = fseLiftMapper.selectByDeptIdAndCode(deptId, code);
        if (fseLift1 != null && !fseLift1.getId().equals(liftId)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }
        FseLift record = new FseLift();
        BeanUtils.copyProperties(request, record);
        record.setId(liftId);
        //保存操作手
        List<FseOperatorDTO> list = request.getOperatorList();
        if (list == null) {
            list = new ArrayList<>();
        }
        record.setOperators(JSON.toJSONString(list));
        fseLiftMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public void del(Integer liftId) {
        logger.info("删除升降机服务,liftId:{}", liftId);
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        if (fseLift == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该升降机不存在");
        }
        if (BindFlag.BIND.getValue().equals(fseLift.getLeftBindFlag()) ||
                BindFlag.BIND.getValue().equals(fseLift.getRightBindFlag())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该升降机已绑定硬件,不能删除");
        }
        fseLiftMapper.deleteLogicById(liftId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bind(FseLiftBindParam request) {
        logger.info("升降机绑定硬件服务,param:{}", request.toString());
        Integer liftId = request.getLiftId();
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        if (fseLift == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该升降机不存在");
        }
        Integer deptId = fseLift.getDeptId();
        String sn = request.getSn();
        String platform = request.getPlatform();
        Integer liftSide = request.getLiftSide();
        FseLiftSide fseLiftSide = FseLiftSide.parseValue(liftSide);
        if (fseLiftSide == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该轿厢方位不存在");
        }
        FseLift fseLift1 = fseLiftMapper.selectByPlatformAndSn(platform, sn);
        if (fseLift1 != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该硬件已被绑定");
        }
        if (StringUtils.isNotBlank(platform) && StringUtils.isNotBlank(fseLift.getPlatform()) &&
                !platform.equals(fseLift.getPlatform())) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "升降机平台不一致");
        }
        if (StringUtils.isNotBlank(platform)) {
            // 更新平台
            fseLiftMapper.updatePlatform(fseLift.getId(), platform);
        }
        FseLiftDTO fseLiftDTO = new FseLiftDTO();
        fseLiftDTO.setCode(fseLift.getCode());
        if (FseLiftSide.LEFT.getValue().equals(fseLiftSide.getValue())) {
            if (BindFlag.BIND.getValue().equals(fseLift.getLeftBindFlag())) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "升降机指定轿厢已绑定硬件,不能重复绑定");
            }
            //修改升降机的绑定状态
            fseLiftMapper.updateLeftBindFlag(liftId, BindFlag.BIND.getValue(), sn, NetState.OFFLINE.getValue());
            // 设置SN
            fseLiftDTO.setLeftSn(fseLift.getLeftSn());
        } else if (FseLiftSide.RIGHT.getValue().equals(fseLiftSide.getValue())) {
            if (BindFlag.BIND.getValue().equals(fseLift.getRightBindFlag())) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "升降机指定轿厢已绑定硬件,不能重复绑定");
            }
            //修改升降机的绑定状态
            fseLiftMapper.updateRightBindFlag(liftId, BindFlag.BIND.getValue(), sn, NetState.OFFLINE.getValue());
            // 设置SN
            fseLiftDTO.setRightSn(fseLift.getRightSn());
        }
        fseLift.setRightSn(sn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbind(FseLiftUnbindParam param) {
        logger.info("升降机解绑硬件服务,param:{}", param);
        Integer liftId = param.getLiftId();
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        if (fseLift == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该升降机不存在");
        }
        Integer liftSide = param.getLiftSide();
        FseLiftSide fseLiftSide = FseLiftSide.parseValue(liftSide);
        if (fseLiftSide == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该轿厢方位不存在");
        }
        //修改升降机的绑定状态
        Integer leftBindFlag = fseLift.getLeftBindFlag();
        Integer rightBindFlag = fseLift.getRightBindFlag();
        Integer unbind = BindFlag.UNBIND.getValue();
        if (FseLiftSide.LEFT.getValue().equals(fseLiftSide.getValue())) {
            if (unbind.equals(leftBindFlag)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "该轿厢方位未绑定硬件");
            }
            fseLiftMapper.updateLeftBindFlag(liftId, unbind, null, NetState.OFFLINE.getValue());
            leftBindFlag = unbind;
        } else if (FseLiftSide.RIGHT.getValue().equals(fseLiftSide.getValue())) {
            if (unbind.equals(rightBindFlag)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "该轿厢方位未绑定硬件");
            }
            fseLiftMapper.updateRightBindFlag(liftId, unbind, null, NetState.OFFLINE.getValue());
            rightBindFlag = unbind;
        }
        // 更新平台
        if (Objects.equals(leftBindFlag, unbind) && Objects.equals(rightBindFlag, unbind)) {
            fseLiftMapper.updatePlatform(fseLift.getId(), null);
        }
    }

    @Override
    public ListData<FseLiftDTO> list(Integer deptId, Integer bindFlag) {
        logger.info("升降机列表服务,deptId:{}", deptId);
        List<Integer> deptIds = sysDeptService.getDescendantDeptIdList(deptId);
        List<FseLiftDTO> list = fseLiftMapper.selectFseLiftList(deptIds, bindFlag);
        return new ListData<>(list);
    }

    @Override
    public List<FseLift> list(Integer deptId, String platform) throws BizException {
        return fseLiftMapper.selectByDeptIdAndPlatform(deptId,platform);
    }

    @Override
    public FseLiftDTO detail(Integer liftId) {
        logger.info("升降机详情服务,liftId:{}", liftId);
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        FseLiftDTO fseLiftDTO = new FseLiftDTO();
        BeanUtils.copyProperties(fseLift, fseLiftDTO);
        fseLiftDTO.setLiftId(fseLift.getId());
        // 查询操作手
        List<FseOperatorDTO> operatorList = parseOperators(fseLiftDTO.getOperators());
        fseLiftDTO.setOperatorList(operatorList);
        fseLiftDTO.setOperators(null);
        // 查询监控列表
        List<FseLiftFvsDeviceDTO> fvsDeviceList = parseFvsDevices(fseLiftDTO.getFvsDevices());
        fseLiftDTO.setFvsList(fvsDeviceList);
        fseLiftDTO.setFvsDevices(null);
        return fseLiftDTO;
    }

    @Override
    public List<FseLiftFvsDeviceDTO> getFvsDeviceList(Integer liftId) throws BizException {
        List<FseLiftFvsDeviceDTO> list = new ArrayList<>();
        FseLift fseLift = fseLiftMapper.selectByPrimaryKey(liftId);
        if (fseLift != null) {
            list = JSON.parseArray(fseLift.getFvsDevices(), FseLiftFvsDeviceDTO.class);
        }
        return list;
    }

    @Override
    public void bindFvs(FseLiftFvsParam fseLiftFvsParam) throws BizException {
        Integer liftId = fseLiftFvsParam.getLiftId();
        //绑定新的监控设备
        List<FseFvsDeviceParam> list = fseLiftFvsParam.getFvsList();
        if (list == null || list.isEmpty()) {
            return;
        }
        List<FseLiftFvsDeviceDTO> fseLiftFvsDevices = new ArrayList<>();
        for (FseFvsDeviceParam fseFvsDeviceParam : list) {
            FseLiftFvsDeviceDTO fseLiftFvsDevice = new FseLiftFvsDeviceDTO();
            fseLiftFvsDevice.setLiftId(liftId);
            fseLiftFvsDevice.setLiftSide(fseFvsDeviceParam.getLiftSide());
            fseLiftFvsDevice.setFvsDeviceId(fseFvsDeviceParam.getFvsDeviceId());
            fseLiftFvsDevice.setFvsDeviceName(fseFvsDeviceParam.getFvsDeviceName());
            fseLiftFvsDevices.add(fseLiftFvsDevice);
        }
        //保存监控绑定信息
        String fvsDevices = JSON.toJSONString(fseLiftFvsDevices);
        fseLiftMapper.updateFvsDevices(fseLiftFvsParam.getLiftId(), fvsDevices);
    }


    /**
     * 处理操作手
     *
     * @param operators 操作手 JSON
     * @return 操作手集合
     */
    private List<FseOperatorDTO> parseOperators(String operators) {
        List<FseOperatorDTO> operatorList = JSON.parseArray(operators, FseOperatorDTO.class);
        if (operatorList == null) {
            operatorList = new ArrayList<>();
        }
        return operatorList;
    }

    /**
     * 处理监控设备
     *
     * @param fvsDevices 监控设备 JSON
     * @return 监控设备集合
     */
    private List<FseLiftFvsDeviceDTO> parseFvsDevices(String fvsDevices) {
        List<FseLiftFvsDeviceDTO> fvsDeviceList = JSON.parseArray(fvsDevices, FseLiftFvsDeviceDTO.class);
        if (fvsDeviceList == null) {
            fvsDeviceList = new ArrayList<>();
        }
        return fvsDeviceList;
    }

    /**
     * 初始化升降机数据信息
     *
     * @param liftId 升降机ID
     */
    private void initLiftData(Integer liftId) {
        // 初始化
        List<FseLiftData> list = new ArrayList<>();
        FseLiftData leftFseLiftData = new FseLiftData();
        leftFseLiftData.setLiftId(liftId);
        leftFseLiftData.setLiftSide(FseLiftSide.LEFT.getValue());
        leftFseLiftData.setHeight(0D);
        leftFseLiftData.setWeight(0D);
        leftFseLiftData.setPersonNo(0);
        leftFseLiftData.setWindSpeed(0D);
        leftFseLiftData.setSpeed(0D);
        leftFseLiftData.setDipAngle(0D);
        leftFseLiftData.setFloor(0);
        leftFseLiftData.setFrontDoorState(1);
        leftFseLiftData.setBackDoorState(1);
        //添加左轿厢数据
        list.add(leftFseLiftData);
        FseLiftData rightFseLiftData = new FseLiftData();
        BeanUtils.copyProperties(leftFseLiftData, rightFseLiftData);
        rightFseLiftData.setLiftSide(FseLiftSide.RIGHT.getValue());
        list.add(rightFseLiftData);
        fseLiftDataMapper.batchInsert(list);
    }


}
